﻿/***********************************************************************************************//**
*\n  @file       usb_serial.c
*\n  @brief      usb串口驱动接口
*\n  @details
*\n -----------------------------------------------------------------------------------
*\n  文件说明：
*\n       1. usb串口驱动接口
*\n       
*\n -----------------------------------------------------------------------------------
*\n  版本:   修改人:       修改日期:        描述:
*\n  V0.01 罗先能        2019.7.26          创建
*\n 
***************************************************************************************************/

/**************************************************************************************************
* 头文件
***************************************************************************************************/
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <stdbool.h>

#if __linux__
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <termios.h>
#include <pthread.h>
#endif

#include "types.h"
#include "printf.h"
#include "usb_serial.h"


/**************************************************************************************************
* 宏定义、结构定义
***************************************************************************************************/


/**************************************************************************************************
* 全局变量声明、定义
***************************************************************************************************/


/**************************************************************************************************
* 私有变量声明、定义
***************************************************************************************************/
static int g_serial_fd = -1;


/**************************************************************************************************
* 私有函数声明、定义
***************************************************************************************************/

// 配置串口速度
static void set_term_options(int fd, unsigned int speed) 
{
	#if __linux__
    struct termios termOptions;

    //获取当前的串口配置
    tcgetattr(fd, &termOptions);

    //配置控制位: Set 8bit data, No parity, stop 1 bit (8N1)
    termOptions.c_cflag &= ~PARENB;               //设为没有奇偶校验: no parity
    termOptions.c_cflag &= ~CSTOPB;               //设为1个停止位:1 stop bit
    termOptions.c_cflag &= ~CSIZE;                //设置字符长度之前,先清字符长度位
    termOptions.c_cflag |= CS8 | CLOCAL | CREAD;  //设为8个数据位, 本地连接, 可以接收字符
    termOptions.c_cflag &= ~CRTSCTS;              //不启用硬件流控制

    //配置输入位
    //禁止(INLCR将NL换行转为CR回车 ICRNL将回车转为换行)
    termOptions.c_iflag &= ~(INLCR | ICRNL | IXON | IXOFF | IXANY);  
    //配置输出位
    //禁止 (处理后输出)
    termOptions.c_oflag &= ~OPOST;                                   
    //配置local
    //禁止 (ICANON使用标准输入模式, ECHO显示输入字符)
    termOptions.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); 

    if (speed == 19200) {
        cfsetispeed(&termOptions, B19200);
        cfsetospeed(&termOptions, B19200);
    } else if (speed == 115200) {
        cfsetispeed(&termOptions, B115200);
        cfsetospeed(&termOptions, B115200);
    } else {
        cfsetispeed(&termOptions, B115200);
        cfsetospeed(&termOptions, B115200);
    }

    tcsetattr(fd, TCSANOW, &termOptions);
	#endif
}


/*获取当前ms数*/
static int get_timer_now(void)
{
    struct timeval now;
    
    gettimeofday(&now, NULL);
    return(now.tv_sec * 1000 + now.tv_usec / 1000);
}



/**************************************************************************************************
* 全局函数声明、定义
***************************************************************************************************/


//打开串口
int serial_open(void)
{
	if (g_serial_fd < 1)
	{
		int fd = open("/dev/ttyGS0", O_RDWR | O_NONBLOCK);
		//	int fd = open("/dev/ttyGS0", O_RDWR	| O_SYNC	| O_NOCTTY | O_NDELAY);
		//	int fd = open("/dev/ttyGS0", O_RDWR | O_NONBLOCK | O_NOCTTY | O_NDELAY);
		if (fd < 1)
		{
			dbg_error("serial_open(/dev/ttyGS0) err!\n");
			return -1;
		}
		
		set_term_options(fd, 115200);
		dbg_info("open /dev/ttyGS0 done.\r\n");
		g_serial_fd = fd;
	}

	return g_serial_fd;
}


// 关闭串口
int serial_close(void)
{
	if (g_serial_fd < 0)
	{
		return 0;
	}
	dbg_info("usb serial close.\r\n");
	close(g_serial_fd);
	g_serial_fd = -1;
	return 0;
}

// 写数据
size_t serial_write(u8 *buf, s32 length)
{
	if (g_serial_fd < 0)
	{
		dbg_error("serial_write fd err!\r\n");
		return -1;
	}

	size_t size = write(g_serial_fd, buf, length);
	if (size < 1)
	{
		dbg_error("write error\n");
		return -1;
	}

	return size;
}

// 读数据
size_t serial_read(OUT u8 *buf, s32 length)
{
	return (int)read(g_serial_fd, buf, length);
}


// 返回: 0 正常， ~0 异常
int serial_check_status(void)
{
	if (g_serial_fd < 0)
	{
		return -1;
	}
	
    struct termios termOptions;
    return tcgetattr(g_serial_fd, &termOptions);
}







